package com.pussinboots.morning.common.security.redis;

import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@SuppressWarnings("all")
public class RedisManager {

    private String host = "127.0.0.1";

    private int port = 6379;

    // 0 - never expire
    private int expire = 0;

    // timeout for jedis try to connect to redis server, not expire time! In milliseconds
    private int timeout = 0;

    private String password = "";

    private JedisPoolConfig poolConfig = new JedisPoolConfig();

    private static JedisPool jedisPool = null;

    public RedisManager() { }

    /**
     * 初始化方法
     */
    public void init() {
        if (jedisPool == null) {
            if (password != null && !"".equals(password)) {
                jedisPool = new JedisPool(poolConfig, host, port, timeout, password);
            }
            else if (timeout != 0) {
                jedisPool = new JedisPool(poolConfig, host, port, timeout);
            }
            else {
                jedisPool = new JedisPool(poolConfig, host, port);
            }

        }
    }

    /**
     * get value from redis
     * 
     * @param key
     * @return
     */
	public byte[] get(byte[] key) {
        byte[] value = null;
        Jedis jedis = jedisPool.getResource();
        try {
            value = jedis.get(key);
        }
        finally {
            jedisPool.returnResource(jedis);
        }
        return value;
    }

    /**
     * set
     * 
     * @param key
     * @param value
     * @return
     */
    public byte[] set(byte[] key, byte[] value) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.set(key, value);
            if (this.expire != 0) {
                jedis.expire(key, this.expire);
            }
        }
        finally {
            jedisPool.returnResource(jedis);
        }
        return value;
    }

    /**
     * set
     * 
     * @param key
     * @param value
     * @param expire
     * @return
     */
    public byte[] set(byte[] key, byte[] value, int expire) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.set(key, value);
            if (expire != 0) {
                jedis.expire(key, expire);
            }
        }
        finally {
            jedisPool.returnResource(jedis);
        }
        return value;
    }

    /**
     * del
     * 
     * @param key
     */
    public void del(byte[] key) {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.del(key);
        }
        finally {
            jedisPool.returnResource(jedis);
        }
    }

    /**
     * flush
     */
    public void flushDB() {
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.flushDB();
        }
        finally {
            jedisPool.returnResource(jedis);
        }
    }

    /**
     * size
     */
    public Long dbSize() {
        Long dbSize = 0L;
        Jedis jedis = jedisPool.getResource();
        try {
            dbSize = jedis.dbSize();
        }
        finally {
            jedisPool.returnResource(jedis);
        }
        return dbSize;
    }

    /**
     * keys
     * 
     * @param regex
     * @return
     */
    public Set<byte[]> keys(String pattern) {
        Set<byte[]> keys = null;
        Jedis jedis = jedisPool.getResource();
        try {
            keys = jedis.keys(pattern.getBytes());
        }
        finally {
            jedisPool.returnResource(jedis);
        }
        return keys;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getExpire() {
        return expire;
    }

    public void setExpire(int expire) {
        this.expire = expire;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public JedisPoolConfig getPoolConfig() {
        return poolConfig;
    }

    public void setPoolConfig(JedisPoolConfig poolConfig) {
        this.poolConfig = poolConfig;
    }
    
	public boolean acquireLock(String lock) {
		boolean success = false;
		Jedis jedis = jedisPool.getResource();
		long value = System.currentTimeMillis() + getExpire() + 1;
		System.out.println(value);
		long acquired = jedis.setnx(lock, String.valueOf(value));
		// SETNX成功，则成功获取一个锁
		if (acquired == 1) {
			jedis.expire(lock, 5 * 60);
			success = true;
			// SETNX失败，说明锁仍然被其他对象保持，检查其是否已经超时
		} else {
			long oldValue = Long.valueOf(jedis.get(lock));

			// 超时
			if (oldValue < System.currentTimeMillis()) {
				String getValue = jedis.getSet(lock, String.valueOf(value));
				// 获取锁成功
				if (Long.valueOf(getValue) == oldValue)
					success = true;
				// 已被其他进程捷足先登了
				else
					success = false;
			}
			// 未超时，则直接返回失败
			else
				success = false;
		}
		jedisPool.returnResource(jedis);
		return success;
	}

	public static void unLock(String key) {
		Jedis jedis = jedisPool.getResource();
		jedis.del(key);
		jedisPool.returnResource(jedis);
	}
}